package edu.uwm.RobberKnight.Model;

import java.awt.Point;
import java.util.Stack;

public class Tile implements java.io.Serializable{
	
	private static final long serialVersionUID = -3619271223200572112L;
	public static int MAX_KNIGHTS = 4;
    private Stack<Knight> _knights;
    private Player _player;
    private TileType _type;
    private char _letter;
    private Point _point;

    protected Tile(TileType type, Player player, char letter) {
        _player = player;
        _type = type;
        _letter = letter;
        _knights = new Stack<Knight>();
        _point = new Point(0, 0);
    }
    
    public boolean place(int x, int y, Board board){
    	setPosition(x, y);
    	return board.placeTile(this);
    }

    /*
     * Returns false if the tile type is lake. Returns true if tile has other
     * type.
     */
    public boolean isPassable() {
        if (_type == TileType.LAKE) {
            return false;
        }
        return true;
    }

    /*
     * Returns the de facto score of the tile based on tile type
     */
    public int getScore() {
        if (_type == TileType.TOWN_PLAIN || _type == TileType.TOWN_FOREST) {
            return 3;
        } else if (_type == TileType.VILLAGE_PLAIN || _type == TileType.VILLAGE_FOREST) {
            return 2;
        } else if (_type == TileType.CASTLE_PLAIN || _type == TileType.CASTLE_FOREST) {
            return 1;
        } else {
            return 0;
        }
    }

    /*
     * Returns the minimum number of knights that should be placed on this tile
     * based on tile type.
     */
    public int getMinDefaultKnight() {
        if (_type == TileType.MOUNTAIN) {
            return 3;
        } else if (_type == TileType.VILLAGE_FOREST || _type == TileType.TOWN_FOREST || _type == TileType.CASTLE_FOREST) {
            return 2;
        } else {
            return 1;
        }
    }

    /*
     * Returns the corresponding enumeration tile type of the tile.
     */
    public TileType getTileType() {
        return _type;
    }

    /*
     * Returns the corresponding letter of the tile.
     */
    public char getLetter() {
        return _letter;
    }

    /*
     * Returns true if the tile type is CASTLE_PLAIN or CASTLE_FOREST. Returns
     * false if tile has other type
     */
    public boolean isCastle() {
        if (_type == TileType.CASTLE_PLAIN || _type == TileType.CASTLE_FOREST) {
            return true;
        }
        return false;
    }

    /*
     * Returns the corresponding point position of the tile
     */
    public Point getPosition() {
        return _point;
    }

    /*
     * Returns the corresponding X position of the tile.
     */
    public int xPosition() {
        return _point.x;
    }

    /*
     * Returns the corresponding y position of the tile.
     */
    public int yPosition() {
        return _point.y;
    }

    // 
    protected void setPosition(int x, int y) {
        _point.x = x;
        _point.y = y;
    }

    /*
     * Returns the player that owns the most top knight on this tile.
     */
    public Player getPlayer() {
        return _player;
    }

    /*
     * Returns the stack of knights currently on the tile.
     */
    @SuppressWarnings("unchecked")
	public Stack<Knight> getKnights() {
        return (Stack<Knight>) _knights.clone();
    }

    /*
     * Adds a knight to the tile's stack of knights.
     */
    protected void addKnights(Knight knight) {
        _knights.add(knight);
    }

    /*
     * placeKnights	Request to place the specified knights onto the specified
     * tile. Returns whether the operation was a success.
     */
    
	public boolean placeKnight(Player currentPlayer, Board board) {
        if (!board.getValidMoves().contains(this)) {
            return false;
        }
        if (board.getPlayableKnights() <= 0) {
            board.setLastPlaced(null);
            return false;
        }
        if(!board.lstUsedPointsContains(_point.x, _point.y)) {
        	 if (getMinDefaultKnight() > currentPlayer.getKnightsSize()) {
                 board.setLastPlaced(null);
                 return false;
        	 }
            for (int i = 0; i < getMinDefaultKnight(); i++) {
                addKnights(currentPlayer.removeKnight());
                board.addLstUsedPoint(_point.x, _point.y);
                board.decrementPlayableKnight();
            }
        } else {
            addKnights(currentPlayer.removeKnight());
            board.decrementPlayableKnight();
        }
		return board.updateKnightDirections(this, currentPlayer);
	}
}